package org.eclipseuseradmin.internal.ui.wizards;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.wizard.WizardPageSupport;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.IWizardNode;
import org.eclipse.jface.wizard.WizardSelectionPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipseuseradmin.internal.ui.NewUserWizardRegistry;
import org.eclipseuseradmin.internal.ui.UserAdminUiPlugin;
import org.eclipseuseradmin.internal.ui.WizardElement;

public class LoginWizardPage extends WizardSelectionPage {

	private DataBindingContext bindingContext;

	private Label loginDescriptionLabel;

	private Label nameLabel;

	private Text nameText;

	private Label passwordLabel;

	private Text passwordText;

	private Label registerDescriptionLabel;

	private TreeViewer viewer;

	private Map<WizardElement, IWizardNode> selectedWizards = new HashMap<WizardElement, IWizardNode>();

	public LoginWizardPage() {

		super("main");
		setTitle(WizardsMessages.get().LoginWizardPage_title);
		setDescription(WizardsMessages.get().LoginWizardPage_description);
		bindingContext = new DataBindingContext();
		WizardPageSupport.create(this, bindingContext);
	}

	public void createControl(Composite parent) {

		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.makeColumnsEqualWidth = true;
		composite.setLayout(layout);
		setControl(composite);

		Composite loginComposite = createLoginControl(composite);
		GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
		loginComposite.setLayoutData(layoutData);

		Composite registerComposite = createRegisterViewer(composite);
		layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
		registerComposite.setLayoutData(layoutData);
	}

	private Composite createLoginControl(Composite parent) {

		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);

		loginDescriptionLabel = new Label(composite, SWT.WRAP);
		loginDescriptionLabel
				.setText(WizardsMessages.get().LoginWizardPage_loginDescription);
		GridData layoutData = new GridData();
		layoutData.horizontalSpan = 2;
		loginDescriptionLabel.setLayoutData(layoutData);

		nameLabel = new Label(composite, SWT.NONE);
		nameLabel.setText(WizardsMessages.get().LoginWizardPage_name);
		layoutData = new GridData();
		layoutData.widthHint = 60;
		nameLabel.setLayoutData(layoutData);

		nameText = new Text(composite, SWT.BORDER);
		layoutData = new GridData(GridData.FILL_HORIZONTAL);
		nameText.setLayoutData(layoutData);
		bindNameValue();

		passwordLabel = new Label(composite, SWT.NONE);
		passwordLabel.setText(WizardsMessages.get().LoginWizardPage_password);
		layoutData = new GridData();
		layoutData.widthHint = 60;
		passwordLabel.setLayoutData(layoutData);

		passwordText = new Text(composite, SWT.BORDER);
		layoutData = new GridData(GridData.FILL_HORIZONTAL);
		passwordText.setLayoutData(layoutData);
		bindPasswordValue();

		return composite;
	}

	private Composite createRegisterViewer(Composite parent) {

		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		composite.setLayout(layout);

		registerDescriptionLabel = new Label(composite, SWT.WRAP);
		registerDescriptionLabel
				.setText(WizardsMessages.get().LoginWizardPage_registerDescription);

		viewer = new TreeViewer(composite, SWT.BORDER | SWT.MULTI);
		GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
		viewer.getControl().setLayoutData(layoutData);
		viewer.setContentProvider(new WizardContentProvider());
		viewer.setLabelProvider(new WizardLabelProvider());
		viewer.setInput(getInput());
		viewer.addSelectionChangedListener(new WizardSelectionListener());

		return composite;
	}

	private void bindNameValue() {

		UpdateValueStrategy updateValueStrategy = new UpdateValueStrategy();
		updateValueStrategy.setBeforeSetValidator(new IValidator() {
			public IStatus validate(Object value) {

				if (((String) value).length() == 0) {
					return ValidationStatus
							.error(WizardsMessages.get().LoginWizardPage_error_name_empty);
				}
				return ValidationStatus.OK_STATUS;
			}
		});
		Binding binding = bindingContext.bindValue(SWTObservables.observeText(
				nameText, SWT.FocusOut), PojoObservables.observeValue(
				getLoginWizard().getNameCallback(), "name"),
				updateValueStrategy, null);
	}

	private void bindPasswordValue() {

		UpdateValueStrategy updateValueStrategy = new UpdateValueStrategy();
		updateValueStrategy.setAfterGetValidator(new IValidator() {
			public IStatus validate(Object value) {

				if (((String) value).length() == 0) {
					return ValidationStatus
							.error(WizardsMessages.get().LoginWizardPage_error_password_empty);
				}
				return ValidationStatus.OK_STATUS;
			}
		});
		updateValueStrategy.setConverter(new IConverter() {

			public Object convert(Object fromObject) {
				return ((String) fromObject).toCharArray();
			}

			public Object getFromType() {
				return String.class;
			}

			public Object getToType() {
				return char[].class;
			}

		});
		Binding binding = bindingContext.bindValue(SWTObservables.observeText(
				passwordText, SWT.FocusOut), PojoObservables.observeValue(
				getLoginWizard().getPasswordCallback(), "password"),
				updateValueStrategy, null);
	}

	private class WizardSelectionListener implements ISelectionChangedListener {

		public void selectionChanged(SelectionChangedEvent event) {

			Object selection = ((IStructuredSelection) event.getSelection())
					.getFirstElement();
			IWizardNode wizardNode = selectedWizards.get(selection);
			if (wizardNode == null) {
				wizardNode = new WizardNode(getLoginWizard(),
						(WizardElement) selection);
			}
			setSelectedNode(wizardNode);
		}

	}

	private NewUserWizardRegistry getInput() {

		return UserAdminUiPlugin.getNewUserWizardsRegistry();
	}

	public LoginWizard getLoginWizard() {
		return (LoginWizard) getWizard();
	}

}
